<?php

/**
 * File upload behavior file.
 *
 * @author hiscaler <hiscaler@gmail.com>
 * @version 0.1 (2010-11-06)
 *
 * Usage:
 * <pre>
    public function behaviors() {
        return array(            
            'UploaderBehavior' => array(
                'class' => 'ext.behaviors.UploaderBehavior',
                'uploadSavedPathAttributes' => array(
                    'picture_saved_path' => array(
                        'fileType' => 'image',
                        'fileName' => 'title',
                        'generateThumbnail' => true,
                    ),
                ),
            ),
        );
    }
 * </pre>
 */
class UploaderBehavior extends CActiveRecordBehavior {

    /**
     *
     * @var string 上传文件保存主目录
     */
    public $uploadRootDirectory = 'uploads';
    /**
     *
     * @var string 上传文件保存子目录（如果不提供，默认创建名称为模型名称的子目录）
     */
    private $_uploadSubDirectory;

    /**
     *
     * @var string 数据库中上传文件路径字段
     */
    public function setUploadSubDirectory($directory) {
        $this->_uploadSubDirectory = $directory;
    }

    public function getUploadSubDirectory() {
        return $this->_uploadSubDirectory;
    }

    /**
     *
     * @return string 上传保存的目录
     */
    public function getUploadDirectory() {
        return Yii::getPathOfAlias('webroot') . DIRECTORY_SEPARATOR
        . $this->uploadRootDirectory . DIRECTORY_SEPARATOR . $this->uploadSubDirectory;
    }

    /**
     *
     * @var array 数据库字段名以及上传类型
     */
    public $uploadSavedPathAttributes;

    /**
     * after Construct
     * @param mixed $event
     */
    public function afterConstruct($event) {
        parent::afterConstruct($event);
        $this->checkDirectory();
    }

    public function checkDirectory() {
        if ($this->uploadSubDirectory == null || empty($this->uploadSubDirectory)) {
            $this->uploadSubDirectory = strtolower(get_class($this->getOwner()));
        }
        if (!is_dir($this->uploadDirectory)) {
            @mkdir($this->uploadDirectory, 0777, true);
            @chmod($this->uploadDirectory, 0777);
            @fclose(fopen($this->uploadDirectory . '/index.htm', 'w'));
            @fclose(fopen($this->uploadDirectory . '/index.html', 'w'));
            @fclose(fopen($this->uploadDirectory . '/default.htm', 'w'));
            @fclose(fopen($this->uploadDirectory . '/default.html', 'w'));
        }
    }

    protected function uuid() {
        $being_timestamp = 1206576000;
        $suffix_len = 3;
        $time = explode(' ', microtime());
        $id = ($time[1] - $being_timestamp) . sprintf('%06u', substr($time[0], 2, 6));
        if ($suffix_len > 0) {
            $id .= substr(sprintf('%010u', mt_rand()), 0, $suffix_len);
        }
        return $id;
    }

    public function getUploadFileSource($attribute) {
        return Yii::app()->baseUrl . "/{$this->uploadRootDirectory}/{$this->uploadSubDirectory}/" . $this->getOwner()->$attribute;
    }

    public function getThumbnailSource($attribute) {
        return (key_exists($attribute, $this->uploadSavedPathAttributes)) ? $this->uploadRootDirectory . DIRECTORY_SEPARATOR . $this->uploadSubDirectory
                . DIRECTORY_SEPARATOR . $this->getOwner()->$attribute : null;
    }

    /**
     * 返回文件保存地址
     * @param string $attribute 字段名称
     * @return string
     */
    public function getUploadFilePath($attribute) {
        return (key_exists($attribute, $this->uploadSavedPathAttributes)) ? $this->uploadDirectory . DIRECTORY_SEPARATOR . $this->getOwner()->$attribute : null;
    }

    /**
     * 返回缩略图文件保存地址
     * @param string $attribute 字段名称
     * @return string
     */
    public function getThumbnailPath($attribute) {
        $filename = (key_exists($attribute, $this->uploadSavedPathAttributes)) ? $this->getOwner()->$attribute : null;
        if ($filename === null) {
            return $filename;
        } else {
            $fileExt = CFileHelper::getExtension($this->getOwner()->$attribute);
            if (in_array(strtolower($fileExt), array('jpg', 'png', 'gif'))) {
                return $this->uploadDirectory . DIRECTORY_SEPARATOR . substr($filename, 0, strlen($filename) - strlen($fileExt) - 1) . '_thumb.' . $fileExt;
            } else {
                return null;
            }
        }
    }

    private $_originalSavedPaths;

    public function afterFind($event) {
        parent::afterFind($event);
        $this->checkDirectory();
        $owner = $this->getOwner();
        foreach ($this->uploadSavedPathAttributes as $attribute => $settings) {
            $this->_originalSavedPaths[$attribute] = $owner->$attribute;
        }
    }

    public function beforeSave($event) {
        parent::beforeSave($event);
        $owner = $this->getOwner();
        $uploadSavedPathAttributes = $this->uploadSavedPathAttributes;
        foreach ($uploadSavedPathAttributes as $attribute => $settings) {
            $uploadingFile = CUploadedFile::getInstance($owner, "{$attribute}");
            if (is_object($uploadingFile) && get_class($uploadingFile) === 'CUploadedFile') {
                if (!$owner->isNewRecord) {
                    $model = $owner->findByPk($owner->primaryKey);
                    @unlink($model->getUploadFilePath($attribute));
                    $thumbnail = $model->getThumbnailPath($attribute);
                    if ($thumbnail !== null) {
                        @unlink($thumbnail);
                    }
                }
                $fileExt = $uploadingFile->getExtensionName();
                $filename = $this->uuid();
                $owner->$attribute = $filename . '.' . $fileExt;
                $uploadingFile->saveAs($this->uploadDirectory . DIRECTORY_SEPARATOR . $filename . '.' . $fileExt);
                $settings = $uploadSavedPathAttributes[$attribute];
                if (isset($settings['generateThumbnail']) && $settings['generateThumbnail'] && isset($settings['fileType']) && $uploadSavedPathAttributes[$attribute]['fileType'] == 'image') {
                    // 生成图片缩略图
                    Yii::app()->thumb->setThumbsDirectory("/" . $this->uploadRootDirectory . DIRECTORY_SEPARATOR . $this->uploadSubDirectory);
                    $thumbnailSettings = UploadSetting::model()->uploadSettingInfos(get_class($owner));
                    Yii::app()->thumb
                            ->load($this->uploadDirectory . DIRECTORY_SEPARATOR . $filename . '.' . $fileExt)
                            ->resize($thumbnailSettings['thumbnail_width'], $thumbnailSettings['thumbnail_height'])
                            ->save($filename . '_thumb.' . $fileExt);
                }
                if (isset($settings['fileSize'])) {
                    $owner->$settings['fileSize'] = $uploadingFile->getSize();
                }
                if (isset($settings['fileExt'])) {
                    $owner->$settings['fileExt'] = $fileExt;
                }
                if (isset($settings['fileName']) && empty($owner->$settings['fileName'])) {
                    $owner->$settings['fileName'] = substr($uploadingFile->getName(), 0, strlen($uploadingFile->getName()) - strlen($uploadingFile->getExtensionName()) - 1);
                }
            } else {
                $owner->$attribute = $this->_originalSavedPaths[$attribute];
            }
        }
        return true;
    }

    public function afterDelete($event) {
        parent::afterDelete($event);
        foreach ($this->uploadSavedPathAttributes as $attribute => $settings) {
            @unlink($this->getUploadFilePath($attribute));
            $thumbnail = $this->getThumbnailPath($attribute);
            if ($thumbnail !== null) {
                @unlink($thumbnail);
            }
        }
    }

}